from engines.Engine import Engine, Features
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *
from settings.settings import *
from network.webengine.filteredwebenginepage import *
from nativePlugins.NativePlugins import triggerLoadedEvent, triggerLoadStartEvent, createLoadEvent, triggerLoadProgressEvent

class YawkEngineView(QWebEngineView):
    parent = None
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.titleChanged.connect(self.adjustTitle)

    def adjustTitle(self):
        try:
            self.parent.setTabText(self.parent.index, self.title())
        except Exception as e:
            print(e)

BUTTON_CSS = "QPushButton {" \
                "width: 32px;" \
                "max-width: 32px;" \
             "}"

class YawkWebEngine(Engine):
    curl = HOME_PAGE
    ENABLE_TAB_FREEZING = False

    def __init__(self, parent, mode="default"):
        super().__init__(parent)

        self.ENABLE_TAB_FREEZING = getSettingAsBool("sys.tab_suspend", False)

        self.engine = YawkEngineView(self)
        self.interceptor = FilteredInterceptor()
        self.profile = QWebEngineProfile()
        self.profile.setRequestInterceptor(self.interceptor)
        if mode == "safe":
            self.profile.setHttpCacheType(QWebEngineProfile.MemoryHttpCache)
            self.profile.setHttpUserAgent("Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0")
            self.profile.settings().setAttribute(QWebEngineSettings.WebRTCPublicInterfacesOnly, False)
            self.profile.settings().setAttribute(QWebEngineSettings.DnsPrefetchEnabled, False)
            self.profile.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
        elif mode == "safe_max" or mode == "tor":
            self.profile.setHttpCacheType(QWebEngineProfile.NoCache)
            self.profile.setHttpUserAgent("Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0")
            self.profile.settings().setAttribute(QWebEngineSettings.WebRTCPublicInterfacesOnly, True)
            self.profile.settings().setAttribute(QWebEngineSettings.DnsPrefetchEnabled, False)
            self.profile.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
        else:
            self.profile.setHttpCacheType(QWebEngineProfile.DiskHttpCache)
            self.profile.setHttpUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36")
            self.profile.settings().setAttribute(QWebEngineSettings.DnsPrefetchEnabled, getSettingAsBool("network.prefetching", False))
            self.profile.settings().setAttribute(QWebEngineSettings.WebRTCPublicInterfacesOnly,
                                                 getSettingAsBool("network.cullwebrtc", False))
        self.profile.settings().setAttribute(QWebEngineSettings.FullScreenSupportEnabled, True)
        self.page = FilteredPage(self.profile, self.engine)
        self.page.loadFinished.connect(self.loaded)
        self.page.loadStarted.connect(self.loadStart)
        self.page.loadProgress.connect(self.loadProgress)
        self.layout.addWidget(self.engine)
        self.engine.setPage(self.page)
        self.page.setUrl(QUrl(HOME_PAGE))

        self.backButton = QPushButton()
        self.backButton.setText("←")
        self.backButton.setToolTip("Go back a page, if possible.")
        self.backButton.setStyleSheet(BUTTON_CSS)
        self.backButton.clicked.connect(self.back)
        self.toolbar.addWidget(self.backButton)

        self.forwardButton = QPushButton()
        self.forwardButton.setText("→")
        self.forwardButton.setToolTip("Go forward a page, if possible.")
        self.forwardButton.setStyleSheet(BUTTON_CSS)
        self.forwardButton.clicked.connect(self.forward)
        self.toolbar.addWidget(self.forwardButton)

        self.urlBar = QLineEdit()
        self.urlBar.returnPressed.connect(self.openPageG)
        self.urlBar.setText(self.page.url().toEncoded().data().decode('utf-8'))
        self.page.urlChanged.connect(self.urlChanged)
        self.toolbar.addWidget(self.urlBar)

    def back(self):
        self.engine.back()

    def forward(self):
        self.engine.forward()

    def closeEngine(self):
        self.engine.close()

    def urlChanged(self, url):
        self.urlBar.setText(url.toEncoded().data().decode('utf-8'))
        self.curl = url.toEncoded().data().decode('utf-8')

    def setTabText(self, index, text):
        self.parent.setTabText(index, text)

    def openPageG(self):
        try:
            self.openPage(self.urlBar.text())
        except Exception as e:
            print(e)

    def openPage(self, url):
        try:
            self.page.setUrl(QUrl(url))
            self.curl = url
        except Exception as e:
            print(e)

    def loaded(self, ok=False):
        if ok:
            p0 = \
                "(function () {" + \
                "var node = document.createElement('style');" \
                "node.innerHTML = " + "\"" + "html, head, body, p, h1, h2, h3, h4, h5, h6 {" \
                                                "font-family: -apple-system, BlinkMacSystemFont, 'BreezeSans', 'Product Sans', 'Google Sans', 'SF Pro Display', 'Segoe UI', 'Arial', sans-serif !important;" \
                                             "}" + "\"" + ";" \
                "document.body.appendChild(node);" \
                "delete node;" \
                "})();"
            self.page.runJavaScript(p0);
            triggerLoadedEvent(createLoadEvent(self.page, self.page.url().toEncoded().data().decode('utf-8')))
        else:
            pass
            # ????

    def supports(self, feature):
        if feature == Features.FEATURE_NATIVE_PLUGIN_JAVASCRIPT_INVOKE\
                or feature == Features.FEATURE_TAB_FREEZE\
                or feature == Features.FEATURE_TAB_DISCARD:
            return True
        else:
            return False

    def supportsTabDiscard(self):
        return True

    def tabState(self, state):
        if not self.ENABLE_TAB_FREEZING:
            return
        if state == Engine.TAB_STATUS_ACTIVE and not self.page.lifecycleState() == QWebEnginePage.LifecycleState.Active:
            self.page.setLifecycleState(QWebEnginePage.LifecycleState.Active)
        elif state == Engine.TAB_STATUS_HIDDEN and not self.page.lifecycleState() == QWebEnginePage.LifecycleState.Frozen:
            self.page.setLifecycleState(QWebEnginePage.LifecycleState.Frozen)
        elif state == Engine.TAB_STATUS_HIDDEN_LONG and not self.page.lifecycleState() == QWebEnginePage.LifecycleState.Discarded:
            self.page.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
        else:
            pass

    def loadStart(self):
        if getSettingAsBool("network.disablewebrtc", False):
            print("loadProgress -> Disabling WebRTC...")
            TO_REMOVE = ["navigator.mediaDevices.getUserMedia", "navigator.webkitGetUserMedia", "navigator.mozGetUserMedia",
                         "navigator.getUserMedia", "window.RTCPeerConnection", "window.MediaStreamTrack",
                         "window.webkitRTCPeerConnection", "window.RTCPeerConnection"]
            for toRemove in TO_REMOVE:
                self.page.runJavaScript(toRemove + " = undefined; delete " + toRemove + ";")
        triggerLoadStartEvent(createLoadEvent(self.page, self.curl))

    def loadProgress(self, progress):
        triggerLoadProgressEvent(createLoadEvent(self.page, self.curl), progress)